package edu.arizona.sista.learn.model.holding;

import java.util.ArrayList;
import java.util.List;

import edu.arizona.sista.learn.model.Interval;
import edu.arizona.sista.learn.model.displaying.Event;
import edu.arizona.sista.learn.util.Computable;

public class HoldingAnObject extends Event{
	public Person _doer;
	public Hand _hand;
	public Object _object; 
	
	public HoldingAnObject(Person doer, Hand hand, Object object, Interval interval) {
		super(interval);
		_doer = doer;
		_hand = hand;
		_object = object;
	}
	
	@Override
	public String toString() {
		String t = "t_"  + _time.start() + "-" + _time.end();
		String s1 = "isa(" + t + ", TimeInterval)\n";
		String s2 = "isa(e_" + _id + ", HoldingAnObject)\n";
		String s3 = "performedBy(e_" + _id + ", " + _doer.getVariableName() + ")\n";
		String s4 = "objectActedOn(e_" + _id + ", object_"  + _object._id + ", Object)\n";
		String s5 = "holdsIn(e_" + _id + ", touches(" + _hand.getVariableName() + ", object_" + _object._id + "))\n";
		String s6 = "temporalExtent(e_" + _id + ", " + t + ")\n";
		return s1 + s2 + s3 + s4 + s5 + s6;
	}

	public static List<HoldingAnObject> getHoldThings(Scene scene) {
		List<Hand> hands = scene.getHands();
		List<Object> objects = scene.getObjects();
		List<HoldingAnObject> output = new ArrayList<HoldingAnObject>();
		for(Hand hand : hands) for (Object object : objects){
			double[] fuzzyFluent = buildFuzzyFluent(hand, object, scene._frames);
			int start = -1;
			int i = 0;
			while(i < fuzzyFluent.length){
				while(i < fuzzyFluent.length && fuzzyFluent[i] < .5) i++;
				start = i;
				while(i < fuzzyFluent.length && fuzzyFluent[i] >= .5) i++;
				//if (i > start + 5){
				if (i > start + 1){
					Person doer = scene.getActorFromBodyPart(hand);
					output.add(new HoldingAnObject(doer, hand, object, new Interval(start, i + 1)));
				}
			}
		}
		for (HoldingAnObject e : output) scene.addEvent(e);
		return output;
	}
	
	private static double[] buildFuzzyFluent(SpatialThing hand, SpatialThing object, int frames) {
		
		// The columns correspond to time intervals of the form (t, t + 1), not to t (with t a frame number) 
		double[] fuzzyFluent = new double[frames - 1];
		for(int i = 1; i < frames; i++){
			fuzzyFluent[i - 1] = Computable.connected(hand.getCoordinate(i - 1), object.getCoordinate(i - 1),
					hand.getCoordinate(i), object.getCoordinate(i),
					hand.getDimension(i - 1), object.getDimension(i - 1),
					hand.getDimension(i), object.getDimension(i));
		}
		return fuzzyFluent;
	}
}
